#!_*_ coding:utf8 _*_
import base64
import urllib
import json
import datetime

import os
from Crypto.Cipher import AES
from django.contrib import auth
from django.contrib.auth.models import User
from django.core.files import File
from django.http import JsonResponse, FileResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.decorators import api_view

from accounts.serializers import UserSeri
from iyinyue import settings
from school.models import School
from student.models import Student, SComment
from student.serializers import StudentSerializer
from teacher.models import Teacher
from teacher.serializers import TeacherSeri
from tools.err import RoingException
from tools.message import check_phone_number, generate_verify_code, send_verify_code_to, real_verify_code
from wx.models import WXUser
from wx.serializers import WXUserSeri

key_address = 'https://api.weixin.qq.com/sns/jscode2session'
appid = 'wx36834261db970d7e'
appsecret = 'f419db207540abd33101782c0889398f'
grant_type = 'authorization_code'
access_token = {}


def unpad(s):
    return s[:-ord(s[len(s) - 1:])]


@api_view(['POST'])
def user_info(request):
    code = request.data.get('code', '')
    req = urllib.request.Request(url='%s?%s' % (key_address, urllib.parse.urlencode({
        'appid': appid,
        'secret': appsecret,
        'js_code': code,
        'grant_type': grant_type
    })))
    res = urllib.request.urlopen(req)
    res = json.loads(res.read())

    openid = res.get('openid', None)
    iuser = None
    try:
        iuser = WXUser.objects.get(openid=openid)
        if iuser.user:
            auth.login(request, iuser.user)
    except WXUser.DoesNotExist:
        userinfo = request.data.get('userInfo', {})
        userinfo['openid'] = openid
        seri = WXUserSeri(data=userinfo)
        if seri.is_valid():
            iuser = seri.save()
    except Exception as e:
        print(e)

    rs = {}
    if iuser:
        rs = WXUserSeri(iuser).data

    return JsonResponse(rs, safe=False)


@api_view(['POST'])
def user_send_verify(request):
    phone = request.data.get('phone', None)
    if not phone or not check_phone_number(phone):
        raise RoingException(code=601, rcode=601, message=u'无效的手机号')

    code = generate_verify_code()
    if not send_verify_code_to(code, phone):
        raise RoingException(message=u'验证码发送失败', code=601, rcode=601)

    request.session['USER-VERIFY'] = real_verify_code(code)
    return JsonResponse({'code': 0, 'message': u'验证码发送成功'})


@api_view(['POST'])
def user_bind(request):
    data = request.data

    verify = request.data.get('verify', None)
    if not verify or request.session.get('USER-VERIFY', None) == real_verify_code(verify):
        raise RoingException(code=601, rcode=601, message=u'无效的验证码')

    phone = request.data.get('phone', None)
    if not phone or not check_phone_number(phone):
        raise RoingException(code=601, rcode=601, message=u'无效的手机号')

    user = None
    try:
        user = User.objects.get(username=phone)
    except User.DoesNotExist:
        user = User.objects.create_user(username=phone, password=phone)
        user.save()
    except:
        raise RoingException(code=601, message=u'设置信息失败')

    name = request.data.get('name', None)
    if name:
        user.first_name = name
        user.save()

    uid = data.get('iuser', None)
    if not uid:
        raise RoingException(code=601, message=u'无效的用户')

    try:
        iuser = WXUser.objects.get(pk=int(uid))
        iuser.user = user
        iuser.save()

        seri = WXUserSeri(iuser)
        return JsonResponse(seri.safe_data)
    except WXUser.DoesNotExist:
        raise RoingException(code=601, message=u'无效的用户')
    except Exception as e:
        raise RoingException(code=601, message=str(e))


@csrf_exempt
def __user_info(request):
    if not request.POST:
        return JsonResponse({'error': 'No params'})

    encryptedData = request.POST.get('encryptedData', '')
    iv = request.POST.get('iv', '')

    code = request.POST.get('code', '')
    req = urllib.request.Request(url='%s?%s' % (key_address, urllib.urlencode({
        'appid': appid,
        'secret': appsecret,
        'js_code': code,
        'grant_type': grant_type
    })))
    res = urllib.request.urlopen(req)
    res = json.loads(res.read())

    """
    session_key = res.get('session_key', '')

    # base64 decode
    sessionKey = base64.b64decode(session_key)
    encryptedData = base64.b64decode(encryptedData)
    iv = base64.b64decode(iv)

    cipher = AES.new(sessionKey, AES.MODE_CBC, iv)

    decrypted = json.loads(unpad(cipher.decrypt(encryptedData)))

    if decrypted['watermark']['appid'] != appid:
        decrypted = {'error': 'Invalid Buffer'}
        
    openid = decrypted.get('openId', None)
    """

    openid = res.get('openid', None)
    iyyuser = {'openid': openid}
    if openid:
        try:
            wx_user = WXUser.objects.get(openid=openid)
            iyyuser.update(WXUserSeri(wx_user).data)
        except WXUser.DoesNotExist as e:
            WXUserSeri(data=res)
            return JsonResponse({'code': 1, 'message': u'请'})

    return JsonResponse(iyyuser, safe=False)


@csrf_exempt
def user_apply(request):
    if not request.body:
        return JsonResponse({'error': 'No params'})

    params = json.loads(request.body)
    name = params.get('name', '')
    openid = params.get('openid', '')
    tid = params.get('tid', None)

    result = {'code': 0,
              'openid': openid}

    try:
        if len(WXUser.objects.filter(openid=openid)) > 0:
            return JsonResponse({'code': 1, 'message': 'Repeat Apply'})

        wx_user = WXUser(openid=openid, name=name, usertype=0)
        if tid:
            teacher = WXUser.objects.get(pk=int(tid)).user.teacher
            user = User.objects.create_user(username=openid, password='123456', first_name=name)
            student = Student.objects.create(me=user)
            teacher.students.add(student)
            user.save()
            student.save()
            teacher.save()
            wx_user.user = user
            wx_user.usertype = 2
        wx_user.save()
        result.update(WXUserSeri(wx_user).data)
    except Exception as e:
        return JsonResponse({'code': 1, 'message': str(e)})

    result['code'] = 0
    return JsonResponse(result)


def school_detail(request):
    if not request.GET:
        return JsonResponse({'error': 'No params'})

    sid = int(request.GET.get('pk', None))
    result = {}
    try:
        school = School.objects.get(pk=sid)
        result['detail'] = school.detail.read()
    except School.DoesNotExist as e:
        return JsonResponse({'code': 1, 'message': 'Not Found'})
    except Exception as e:
        return JsonResponse({'code': 1, 'message': str(e)})

    return JsonResponse(result)


def school_teacher(request):
    school_id = None
    teacher_id = None
    student_id = None
    if request.GET:
        school_id = request.GET.get('sid', None)
        teacher_id = request.GET.get('tid', None)
        student_id = request.GET.get('stid', None)

    try:
        teachers = []
        if teacher_id:
            teacher = Teacher.objects.get(pk=int(teacher_id))
            teachers.append(teacher)
        elif school_id:
            teachers = School.objects.get(pk=int(school_id)).teachers
        elif student_id:
            teachers = Student.objects.get(pk=int(student_id)).student_teachers
        else:
            teachers = Teacher.objects.all()
        return JsonResponse(TeacherSeri(teachers, many=True, context={'excludes': ['students', 'videos']}).data,
                            safe=False)
    except Teacher.DoesNotExist as e:
        return JsonResponse({'code': 1, 'message': 'Not Found'})
    except Exception as e:
        return JsonResponse({'code': 1, 'message': str(e)})

    return JsonResponse({'code': 0})


def teacher_student(request):
    teacher_id = None
    student_id = None
    if request.GET:
        teacher_id = request.GET.get('tid', None)
        student_id = request.GET.get('sid', None)

    try:
        students = []
        if teacher_id:
            students = Teacher.objects.get(pk=int(teacher_id)).students
        elif student_id:
            s = Student.objects.get(pk=int(student_id))
            students.append(s)
        else:
            students = Student.objects.all()
        return JsonResponse(StudentSerializer(students, many=True).data, safe=False)
    except Exception as e:
        return JsonResponse({'code': 1, 'message': str(e)})


@csrf_exempt
def add_comment(request):
    if not request.body:
        return JsonResponse({'code': 1, 'message': 'No Params'})

    params = json.loads(request.body)
    tid = params.get('tid', None)
    sid = params.get('sid', None)
    comment = params.get('comment', None)
    if tid and sid and comment:
        try:
            s = Student.objects.get(pk=int(sid))
            sc = SComment.objects.create(**comment)
            s.comments.add(sc)
            s.save()
            return JsonResponse(StudentSerializer(s).data, safe=False)
        except Exception as e:
            return JsonResponse({'code': 1, 'messge': str(e)})

    return JsonResponse({'code': 1, 'message': 'Params error'})


@csrf_exempt
def gen_code(request):
    """生成对应的二编码"""
    if not request.body:
        return JsonResponse({'code': 1, 'message': 'Params error'})

    params = json.loads(request.body)
    openid = params.get('openid', None)
    wxuser = None
    if not openid:
        return JsonResponse({'code': 1, 'message': 'No OpenId'})
    else:
        try:
            wxuser = WXUser.objects.get(openid=openid)
        except Exception as e:
            return JsonResponse({'code': 1, 'message': 'WXUser Not Found'})

    token_address = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + appid + '&secret=' + appsecret
    token = access_token.get('token', None)
    token_time = access_token.get('time', None)
    if not token or not token_time or (datetime.datetime.now() - token_time).seconds > 2 * 3600 - 100:
        """token 不存在，token更新的时间不存在，token更新时间过早"""
        res = urllib2.urlopen(token_address)
        res = json.loads(res.read())
        if res:
            access_token['token'] = res.get('access_token', '')
            access_token['time'] = datetime.datetime.now()
            token = access_token['token']

    # code_address = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' + token
    code_address = 'https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=' + token
    req = urllib2.Request(code_address, data=json.dumps(params), headers={'Content-Type': 'application/json'})
    res = urllib2.urlopen(req)

    try:
        code_root = os.path.join(settings.MEDIA_ROOT, 'code')
        if not os.path.exists(code_root):
            os.mkdir(code_root)
        code_path = os.path.join(code_root, openid + '.png')
        code_file = open(code_path, 'wb+')
        code_file.write(res.read())

        wxuser.code = File(code_file)
        wxuser.save()
        return JsonResponse(WXUserSeri(wxuser).data, safe=False)
    except Exception as e:
        return JsonResponse({'code': 1, 'message': str(e)})

    return JsonResponse({'code': 0, 'message': code_path})
